package com.zzh.partnersys.ai.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzh.partnersys.ai.entity.AiAssistantDO;
import com.zzh.partnersys.ai.entity.AiAssistantDocumentDO;
import com.zzh.partnersys.ai.entity.request.AiAssistantDocRequest;
import com.zzh.partnersys.ai.entity.response.AiAssistantDocumentVO;
import com.zzh.partnersys.ai.entity.response.AiAssistantVO;
import com.zzh.partnersys.ai.mapper.AiAssistantMapper;
import com.zzh.partnersys.ai.service.AiAssistantDocumentService;
import com.zzh.partnersys.ai.service.AiAssistantService;
import com.zzh.partnersys.ai.util.RedisCacheUtil;
import com.zzh.partnersys.common.enums.StatusEnum;
import com.zzh.partnersys.common.exception.BusinessException;
import com.zzh.partnersys.common.exception.ResultCodeEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * AI助手表 服务实现类
 * </p>
 *
 * @author zzh
 * @since 2025-01-XX
 */
@Slf4j
@Service
public class AiAssistantServiceImpl extends ServiceImpl<AiAssistantMapper, AiAssistantDO> implements AiAssistantService {

    @Resource
    private RedisCacheUtil redisCacheUtil;

    @Resource
    private AiAssistantDocumentService aiAssistantDocumentService;

    /**
     * Redis缓存Key前缀
     */
    private static final String CACHE_KEY_PREFIX = "ai:assistant:";
    private static final String USER_ASSISTANTS_KEY_PREFIX = "ai:assistant:user:";
    private static final long CACHE_EXPIRE_TIME = 24; // 缓存过期时间（小时）

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AiAssistantDO createAssistant(Long userId, String assistantName, String roleDesc, String greeting, List<AiAssistantDocRequest> docList) {
        // 1. 参数校验
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (StrUtil.isBlank(assistantName)) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (StrUtil.isBlank(roleDesc)) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }

        // 2. 检查是否已有默认助手，如果没有则设置当前为默认
        AiAssistantDO defaultAssistant = getDefaultAssistant(userId);
        Integer isDefault = (defaultAssistant == null) ? 1 : 0;

        // 3. 创建助手对象
        AiAssistantDO assistant = new AiAssistantDO();
        assistant.setUserId(userId);
        assistant.setAssistantName(assistantName);
        assistant.setRoleDesc(roleDesc);
        assistant.setGreeting(greeting);
        assistant.setIsDefault(isDefault);
        assistant.setStatus(StatusEnum.ENABLED.getCode()); // 默认启用
        assistant.setCreateTime(LocalDateTime.now());
        assistant.setUpdateTime(LocalDateTime.now());
        assistant.setIsDelete(0);

        // 4. 保存到数据库
        boolean saved = this.save(assistant);
        if (!saved) {
            throw new BusinessException(ResultCodeEnum.SYSTEM_ERROR);
        }

        // 保存AI助手的文档保存
        List<AiAssistantDocumentDO> documentList = docList.stream().map(doc -> {
            AiAssistantDocumentDO document = new AiAssistantDocumentDO();
            document.setAssistantId(assistant.getId());
            document.setDocumentName(doc.getDocName());
            document.setDocumentType(doc.getDocType());
            document.setDocumentUrl(doc.getDocUrl());
            document.setDocumentSize(doc.getDocSize());
            document.setUploadTime(LocalDateTime.now());
            document.setCreateTime(LocalDateTime.now());
            document.setIsDelete(0);
            document.setStatus(StatusEnum.ENABLED.getCode());
            return document;
        }).toList();
        aiAssistantDocumentService.saveBatch(documentList);

        // 注意：文档解析和存储到 ES 通过单独的接口异步处理，前端调用 /document/parse/{assistantId} 接口
        // 这样可以实时推送解析进度给前端

        // 5. 清除用户助手列表缓存
        clearUserAssistantsCache(userId);

        log.info("创建AI助手成功，assistantId: {}, userId: {}", assistant.getId(), userId);
        return assistant;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AiAssistantDO updateAssistant(Long assistantId, Long userId, String assistantName, String roleDesc, String greeting) {
        // 1. 参数校验
        if (assistantId == null || assistantId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }

        // 2. 查询助手并校验权限
        AiAssistantDO assistant = this.getById(assistantId);
        if (assistant == null) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (!assistant.getUserId().equals(userId)) {
            throw new BusinessException(ResultCodeEnum.NO_AUTH);
        }

        // 3. 更新字段
        if (StringUtils.isNotBlank(assistantName)) {
            assistant.setAssistantName(assistantName);
        }
        if (StringUtils.isNotBlank(roleDesc)) {
            assistant.setRoleDesc(roleDesc);
        }
        if (greeting != null) {
            assistant.setGreeting(greeting);
        }
        assistant.setUpdateTime(LocalDateTime.now());

        // 4. 保存更新
        boolean updated = this.updateById(assistant);
        if (!updated) {
            throw new BusinessException(ResultCodeEnum.SYSTEM_ERROR);
        }

        // 5. 清除缓存
        clearAssistantCache(assistantId);
        clearUserAssistantsCache(userId);

        log.info("更新AI助手成功，assistantId: {}, userId: {}", assistantId, userId);
        return assistant;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAssistant(Long assistantId, Long userId) {
        // 1. 参数校验
        if (assistantId == null || assistantId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }

        // 2. 查询助手并校验权限
        AiAssistantDO assistant = this.getById(assistantId);
        if (assistant == null) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (!assistant.getUserId().equals(userId)) {
            throw new BusinessException(ResultCodeEnum.NO_AUTH);
        }

        // 3. 逻辑删除助手
        boolean deleted = this.removeById(assistantId);
        if (!deleted) {
            throw new BusinessException(ResultCodeEnum.SYSTEM_ERROR);
        }

        // 4. 如果删除的是默认助手，需要设置其他助手为默认
        if (assistant.getIsDefault() == 1) {
            // 查找用户的其他助手，设置第一个为默认
            List<AiAssistantDO> otherAssistants = this.list(
                    new LambdaQueryWrapper<AiAssistantDO>()
                            .eq(AiAssistantDO::getUserId, userId)
                            .ne(AiAssistantDO::getId, assistantId)
                            .eq(AiAssistantDO::getIsDelete, 0)
                            .orderByAsc(AiAssistantDO::getCreateTime)
                            .last("LIMIT 1")
            );
            if (!otherAssistants.isEmpty()) {
                AiAssistantDO newDefault = otherAssistants.get(0);
                newDefault.setIsDefault(1);
                this.updateById(newDefault);
                clearAssistantCache(newDefault.getId());
            }
        }

        // 5. 清除缓存
        clearAssistantCache(assistantId);
        clearUserAssistantsCache(userId);

        log.info("删除AI助手成功，assistantId: {}, userId: {}", assistantId, userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setDefaultAssistant(Long assistantId, Long userId) {
        // 1. 参数校验
        if (assistantId == null || assistantId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }

        // 2. 查询助手并校验权限
        AiAssistantDO assistant = this.getById(assistantId);
        if (assistant == null) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (!assistant.getUserId().equals(userId)) {
            throw new BusinessException(ResultCodeEnum.NO_AUTH);
        }

        // 3. 取消其他助手的默认状态
        this.update(
                new LambdaUpdateWrapper<AiAssistantDO>()
                        .eq(AiAssistantDO::getUserId, userId)
                        .ne(AiAssistantDO::getId, assistantId)
                        .set(AiAssistantDO::getIsDefault, 0)
        );

        // 4. 设置当前助手为默认
        assistant.setIsDefault(1);
        assistant.setUpdateTime(LocalDateTime.now());
        boolean updated = this.updateById(assistant);
        if (!updated) {
            throw new BusinessException(ResultCodeEnum.SYSTEM_ERROR);
        }

        // 5. 清除缓存
        clearUserAssistantsCache(userId);
        // 清除所有用户助手的缓存（因为默认状态改变了）
        List<AiAssistantDO> userAssistants = this.list(
                new LambdaQueryWrapper<AiAssistantDO>()
                        .eq(AiAssistantDO::getUserId, userId)
                        .eq(AiAssistantDO::getIsDelete, 0)
        );
        for (AiAssistantDO a : userAssistants) {
            clearAssistantCache(a.getId());
        }

        log.info("设置默认助手成功，assistantId: {}, userId: {}", assistantId, userId);
        return true;
    }

    @Override
    public AiAssistantDO getDefaultAssistant(Long userId) {
        if (userId == null || userId <= 0) {
            return null;
        }

        // 先从缓存获取用户助手列表
        List<AiAssistantVO> assistants = getUserAssistants(userId);
        if (assistants != null && !assistants.isEmpty()) {
            AiAssistantVO defaultAssistantVO = assistants.stream()
                    .filter(a -> a.getIsDefault() == 1)
                    .findFirst()
                    .orElse(null);
            
            // 将VO转换为DO返回
            if (defaultAssistantVO != null) {
                AiAssistantDO assistantDO = new AiAssistantDO();
                assistantDO.setId(defaultAssistantVO.getId());
                assistantDO.setUserId(defaultAssistantVO.getUserId());
                assistantDO.setAssistantName(defaultAssistantVO.getAssistantName());
                assistantDO.setRoleDesc(defaultAssistantVO.getRoleDesc());
                assistantDO.setGreeting(defaultAssistantVO.getGreeting());
                assistantDO.setIsDefault(defaultAssistantVO.getIsDefault());
                assistantDO.setStatus(defaultAssistantVO.getStatus());
                assistantDO.setCreateTime(defaultAssistantVO.getCreateTime());
                assistantDO.setUpdateTime(defaultAssistantVO.getUpdateTime());
                assistantDO.setIsDelete(defaultAssistantVO.getIsDelete());
                return assistantDO;
            }
        }

        return null;
    }

    @Override
    public List<AiAssistantVO> getUserAssistants(Long userId) {
        if (userId == null || userId <= 0) {
            return null;
        }

        // 1. 先从Redis缓存获取（缓存中存储的是AiAssistantVO列表）
        String cacheKey = USER_ASSISTANTS_KEY_PREFIX + userId;
        List<AiAssistantVO> cachedAssistants = redisCacheUtil.getCacheList(cacheKey);
        if (cachedAssistants != null && !cachedAssistants.isEmpty()) {
            log.debug("从缓存获取用户助手列表，userId: {}", userId);
            return cachedAssistants;
        }

        // 2. 从数据库查询助手列表
        List<AiAssistantDO> assistants = this.list(
                new LambdaQueryWrapper<AiAssistantDO>()
                        .eq(AiAssistantDO::getUserId, userId)
                        .eq(AiAssistantDO::getIsDelete, 0)
                        .orderByDesc(AiAssistantDO::getIsDefault)
                        .orderByDesc(AiAssistantDO::getCreateTime)
        );

        if (assistants == null || assistants.isEmpty()) {
            return new ArrayList<>();
        }

        // 3. 为每个助手查询并组装文档列表
        List<AiAssistantVO> assistantVOList = assistants.stream().map(assistant -> {
            AiAssistantVO assistantVO = new AiAssistantVO();
            // 复制助手基本信息
            assistantVO.setId(assistant.getId());
            assistantVO.setUserId(assistant.getUserId());
            assistantVO.setAssistantName(assistant.getAssistantName());
            assistantVO.setRoleDesc(assistant.getRoleDesc());
            assistantVO.setGreeting(assistant.getGreeting());
            assistantVO.setIsDefault(assistant.getIsDefault());
            assistantVO.setStatus(assistant.getStatus());
            assistantVO.setCreateTime(assistant.getCreateTime());
            assistantVO.setUpdateTime(assistant.getUpdateTime());
            assistantVO.setIsDelete(assistant.getIsDelete());

            // 查询该助手的文档列表
            List<AiAssistantDocumentDO> documents = aiAssistantDocumentService.getAssistantDocuments(assistant.getId());
            
            // 转换为VO
            List<AiAssistantDocumentVO> documentVOList = new ArrayList<>();
            if (documents != null && !documents.isEmpty()) {
                documentVOList = documents.stream()
                        .map(doc -> {
                            AiAssistantDocumentVO docVO = new AiAssistantDocumentVO();
                            docVO.setDocName(doc.getDocumentName());
                            docVO.setDocUrl(doc.getDocumentUrl());
                            docVO.setDocSize(doc.getDocumentSize());
                            return docVO;
                        })
                        .collect(Collectors.toList());
            }
            assistantVO.setDocumentList(documentVOList);

            return assistantVO;
        }).collect(Collectors.toList());

        // 4. 存入缓存
        redisCacheUtil.setCacheList(cacheKey, assistantVOList, (int) CACHE_EXPIRE_TIME, TimeUnit.HOURS);
        log.debug("用户助手列表已缓存，userId: {}, count: {}", userId, assistantVOList.size());

        return assistantVOList;
    }

    @Override
    public AiAssistantDO getAssistantById(Long assistantId) {
        if (assistantId == null || assistantId <= 0) {
            return null;
        }

        // 1. 先从Redis缓存获取
        String cacheKey = CACHE_KEY_PREFIX + assistantId;
        AiAssistantDO cachedAssistant = redisCacheUtil.getCacheObject(cacheKey);
        if (cachedAssistant != null) {
            log.debug("从缓存获取助手，assistantId: {}", assistantId);
            return cachedAssistant;
        }

        // 2. 从数据库查询
        AiAssistantDO assistant = this.getById(assistantId);
        if (assistant == null || assistant.getIsDelete() == 1) {
            return null;
        }

        // 3. 存入缓存
        if (assistant != null) {
            redisCacheUtil.setCacheObject(cacheKey, assistant, (int) CACHE_EXPIRE_TIME, TimeUnit.HOURS);
            log.debug("助手信息已缓存，assistantId: {}", assistantId);
        }

        return assistant;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAssistantStatus(Long assistantId, Long userId, Integer status) {
        // 1. 参数校验
        if (assistantId == null || assistantId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (userId == null || userId <= 0) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (status == null || (status != 0 && status != 1)) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }

        // 2. 查询助手并校验权限
        AiAssistantDO assistant = this.getById(assistantId);
        if (assistant == null) {
            throw new BusinessException(ResultCodeEnum.PARAMS_ERROR);
        }
        if (!assistant.getUserId().equals(userId)) {
            throw new BusinessException(ResultCodeEnum.NO_AUTH);
        }

        // 3. 更新状态
        assistant.setStatus(status);
        assistant.setUpdateTime(LocalDateTime.now());
        boolean updated = this.updateById(assistant);
        if (!updated) {
            throw new BusinessException(ResultCodeEnum.SYSTEM_ERROR);
        }

        // 4. 清除缓存
        clearAssistantCache(assistantId);
        clearUserAssistantsCache(userId);

        log.info("更新助手状态成功，assistantId: {}, userId: {}, status: {}", assistantId, userId, status);
        return true;
    }

    /**
     * 清除助手缓存
     */
    private void clearAssistantCache(Long assistantId) {
        String cacheKey = CACHE_KEY_PREFIX + assistantId;
        redisCacheUtil.deleteObject(cacheKey);
    }

    /**
     * 清除用户助手列表缓存
     */
    private void clearUserAssistantsCache(Long userId) {
        String cacheKey = USER_ASSISTANTS_KEY_PREFIX + userId;
        redisCacheUtil.deleteObject(cacheKey);
    }
}

